package com.xinqi.modules.sys.gpt.manager.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xinqi.common.base.error.CommonErrors;
import com.xinqi.common.core.constant.GptConstants;
import com.xinqi.common.core.utils.MessageUtils;
import com.xinqi.common.mybatis.data.service.impl.BaseServiceImpl;
import com.xinqi.modules.sys.gpt.domain.DayCountEntity;
import com.xinqi.modules.sys.gpt.manager.DayCountManager;
import com.xinqi.modules.sys.gpt.mapper.DayCountMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.Objects;

/**
 * 每日用户配额管理层实现
 *
 * @author: yyzhen
 * @date: 2023/05/23
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DayCountManagerImpl extends BaseServiceImpl<DayCountMapper, DayCountEntity> implements DayCountManager {

    /**
     * 获取用户今日配额（此方法初始化用户配额）
     *
     * @param userId
     * @return
     */
    @Override
    public DayCountEntity findByUserAndInit(Long userId) {
        LocalDate now = LocalDate.now();
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(userId), MessageUtils.message("user.id.not.black"));
        DayCountEntity count = this.baseMapper.selectOne(wrapper(userId));
        if (Objects.isNull(count)) {
            count = initDayCount(userId, now);
        } else if (!now.isEqual(count.getDay())) {
            count.setDay(now);
            count.setUsedCount(0);
            this.baseMapper.updateById(count);
        }
        return count;
    }

    /**
     * 获取用户配额（此方法不初始化用户配额）
     *
     * @param userId
     * @return
     */
    @Override
    public DayCountEntity findByUser(Long userId) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(userId), MessageUtils.message("user.id.not.black"));
        return this.baseMapper.selectOne(wrapper(userId));
    }

    private LambdaQueryWrapper<DayCountEntity> wrapper(Long userId) {
        LambdaQueryWrapper<DayCountEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DayCountEntity::getUserId, userId)
            .last("LIMIT 1");
        return queryWrapper;
    }

    /**
     * 请求失败-- 回调 -- 恢复一次配额
     *
     * @param userId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean recoveryByUser(Long userId) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(userId), MessageUtils.message("user.id.not.black"));
        DayCountEntity count = this.findByUser(userId);
        if (Objects.isNull(count)) {
            return true;
        }
        //已用次数
        Integer usedCount = count.getUsedCount();
        if (0 < usedCount) {
            count.setUsedCount(usedCount - 1);
        }
        return this.baseMapper.updateById(count) > 0;
    }

    /**
     * 初始化用户某天的配额
     * 未产生次数变化则不在数据库进行数据存储
     * 谨防数据量过大
     *
     * @param userId
     * @param now
     */
    private DayCountEntity initDayCount(Long userId, LocalDate now) {
        DayCountEntity entity = new DayCountEntity();
        entity.setUserId(userId);
        entity.setDay(now);
        entity.setShareCount(0);
        entity.setUsedCount(0);
        entity.setAvailableCount(GptConstants.DEFAULT_QUOTA);
        try {
            this.baseMapper.insert(entity);
        } catch (Exception e) {
            entity = findByUser(userId);
        }
        return entity;
    }


}
